package com.zl.tby.icc;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.zl.tby.core.base.util.ToolsUtil;
import com.zl.tby.core.common.R;
import com.zl.tby.model.TbyUavRecord;
import org.noear.wood.utils.StringUtils;

import javax.crypto.Cipher;
import java.net.URLEncoder;
import java.security.KeyFactory;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.X509EncodedKeySpec;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * @author changpeng
 * @version 1.0
 * @since 2024/9/15 9:58
 */
public class IccUtil {

    //private final static String IP = "https://175.44.137.58:18443";
    private static String IP = "";
    private static String IN_IP = "";
    private static String USER_NAME = "";
    private static String PASSWORD = "";
    private static String CLIENT_ID = "";
    private static String CLIENT_SECRET = "";

    public static void init(String ip, String inIp, String userName, String password, String clientId, String clientSecret) {
        IccUtil.IP = ip;
        IccUtil.IN_IP = inIp;
        IccUtil.USER_NAME = userName;
        IccUtil.PASSWORD = password;
        IccUtil.CLIENT_ID = clientId;
        IccUtil.CLIENT_SECRET = clientSecret;
    }

    public static String getRequestUrl(String url) {
        return IP + url;
    }

    public static String getInRequestUrl(String url) {
        //return IN_IP + url;
        return IP + url;
    }

    /**
     * 获取公钥
     * @return 公钥
     */
    private static String getPublicKey() {
        try {
            ObjectMapper mapper = new ObjectMapper();
            String responseData = IccHttpsURLConnectionUtil.doGet(IccUtil.getRequestUrl("/evo-apigw/evo-oauth/1.0.0/oauth/public-key"), null);
            IccResponse response = mapper.readValue(responseData, IccResponse.class);
            Map<String, String> map = (Map<String, String>) response.getData();
            return map.get("publicKey");
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return null;
    }

    /**
     * 登录方法
     * @return 用户信息及token
     */
    public static R<IccToken> login() {
        try {
            Gson gson = new Gson();
            String publicKey = getPublicKey();
            if (StringUtils.isEmpty(publicKey)) {
                return R.failed("公钥异常");
            }
            JSONObject data = new JSONObject();
            data.put("grant_type", "password");
            data.put("username", USER_NAME);
            data.put("password", encrypt(PASSWORD, publicKey));
            data.put("client_id", CLIENT_ID);
            data.put("client_secret", CLIENT_SECRET);
            data.put("public_key", publicKey);
            String responseDate = IccHttpsURLConnectionUtil.doPost(getRequestUrl("/evo-apigw/evo-oauth/1.0.0/oauth/extend/token"), JSON.toJSONString(data), null);
            IccResponse<IccToken> response = gson.fromJson(responseDate, new TypeToken<IccResponse<IccToken>>(){}.getType());
            return R.ok(response.getData());
        } catch (Exception ex) {
            ex.printStackTrace();
            return null;
        }
    }

    public static R<IccDeviceInfo> getDeviceInformation(String deviceCode) {
        IccToken token = IccTokenCache.getInstance().getToken();
        if (token == null) {
            return R.failed("token为空");
        }
        String responseData = IccHttpsURLConnectionUtil.doGet(getRequestUrl("/evo-apigw/evo-brm/1.0.0/device/" + deviceCode), token.getHeaderToken());
        Gson gson = new Gson();
        try {
            IccResponse<IccDeviceInfo> response = gson.fromJson(responseData, new TypeToken<IccResponse<IccDeviceInfo>>(){}.getType());
            return R.ok(response.getData());
        } catch (Exception ex) {
            ex.printStackTrace();
            return R.failed(ex.getMessage());
        }
    }

    public static R<IccVideoInfo> getVideoUrl(String channelId, String streamType, String dataType) {
        IccToken token = IccTokenCache.getInstance().getToken();
        if (token == null) {
            return R.failed("token为空");
        }
        JSONObject data = new JSONObject();
        JSONObject jsonObject = new JSONObject();
        data.put("data", jsonObject);
        jsonObject.put("channelId", channelId);
        jsonObject.put("streamType", streamType);
        jsonObject.put("type", "rtsp");
        jsonObject.put("dataType", dataType);
        String responseData = IccHttpsURLConnectionUtil.doPost(getRequestUrl("/evo-apigw/admin/API/MTS/Video/StartVideo"), JSON.toJSONString(data), token.getHeaderToken());
        try {
            Gson gson = new Gson();
            IccResponse<IccVideoInfo> response = gson.fromJson(responseData, new TypeToken<IccResponse<IccVideoInfo>>(){}.getType());
            if (response.getCode().compareTo(1000) == 0) {
                return R.ok(response.getData());
            }
            return R.failed(response.getErrMsg());
        } catch (Exception ex) {
            ex.printStackTrace();
            return R.failed(ex.getMessage());
        }
    }

    public static R<List<IccDeviceInfo>> deviceList(Integer pageSize, Integer deviceCategory, String ips) {
        IccToken token = IccTokenCache.getInstance().getToken();
        if (token == null) {
            return R.failed("token为空");
        }
        JSONObject data = new JSONObject();
        data.put("pageSize", pageSize);
        data.put("syncVirtualData", 0);
        if (deviceCategory != null && deviceCategory.compareTo(0) != 0) {
            JSONArray array = new JSONArray();
            array.add(deviceCategory);
            data.put("categorys", array);
        }
        if (StringUtils.isNotEmpty(ips)) {
            JSONArray array = new JSONArray();
            String[] ipArray = ips.split(",");
            for (String ip : ipArray) {
                array.add(ip);
            }
            data.put("deviceIps", array);
        }
        String responseData = IccHttpsURLConnectionUtil.doPost(getRequestUrl("/evo-apigw/evo-brm/1.2.0/device/subsystem/page"), JSON.toJSONString(data), token.getHeaderToken());
        try {
            Gson gson = new Gson();
            IccResponse<IccPageVo<IccDeviceInfo>> response = gson.fromJson(responseData, new TypeToken<IccResponse<IccPageVo<IccDeviceInfo>>>(){}.getType());
            return R.ok(response.getData().getPageData());
        } catch (Exception ex) {
            ex.printStackTrace();
            return R.failed(ex.getMessage());
        }
    }

    public static R<IccResponse<IccPageVo<IccCarRecord>>> searchCarRecordList(Integer pageNum, Integer pageSize, Date startDate, Date endDate) throws Exception {
        IccToken token = IccTokenCache.getInstance().getToken();
        if (token == null) {
            return R.failed("token为空");
        }
        StringBuilder builder = new StringBuilder();
        builder.append(getRequestUrl("/evo-apigw/evo-car/1.0.0/carCommonQuery/getPicRecords"));
        JSONObject data = new JSONObject();
        data.put("page", pageNum);
        data.put("rows", pageSize);
        data.put("startDate", (startDate.getTime() / 1000) + "");
        data.put("endDate", (endDate.getTime() / 1000) + "");
        JSONObject body = new JSONObject();
        body.put("data", data);
        String responseData = IccHttpsURLConnectionUtil.doPost(builder.toString(), JSON.toJSONString(body), token.getHeaderToken());
        try {
            Gson gson = new Gson();
            IccResponse<IccPageVo<IccCarRecord>> response = gson.fromJson(responseData, new TypeToken<IccResponse<IccPageVo<IccCarRecord>>>(){}.getType());
            return R.ok(response);
        } catch (Exception ex) {
            ex.printStackTrace();
            return R.failed(ex.getMessage());
        }
    }

    public static R<IccResponse<IccPageVo<IccFaceInfo>>> searchFaceRecordList(Integer pageNum, Integer pageSize, String startDate) throws Exception {
        IccToken token = IccTokenCache.getInstance().getToken();
        if (token == null) {
            return R.failed("token为空");
        }
        System.out.println(token.getAccess_token());
        StringBuilder builder = new StringBuilder();
        builder.append("/evo-apigw/evo-face/faceQuery/page?searchType=2")
                .append("&pageNum=").append(pageNum)
                .append("&pageSize=").append(pageSize)
                .append("&startTime=").append(URLEncoder.encode(startDate));
        String responseData = IccHttpsURLConnectionUtil.doGet(IccUtil.getRequestUrl(builder.toString()), token.getHeaderToken());
        try {
            Gson gson = new Gson();
            IccResponse<IccPageVo<IccFaceInfo>> response = gson.fromJson(responseData, new TypeToken<IccResponse<IccPageVo<IccFaceInfo>>>(){}.getType());
            return R.ok(response);
        } catch (Exception ex) {
            ex.printStackTrace();
            return R.failed(ex.getMessage());
        }
    }

    public static String encrypt(String password, String publicKey) throws Exception {
        //base64编码的公钥
        byte[] decoded = java.util.Base64.getDecoder().decode(publicKey);
        RSAPublicKey pubKey = (RSAPublicKey) KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(decoded));
        //RSA加密
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.ENCRYPT_MODE, pubKey);
        String outStr;
        byte[] inputArray = password.getBytes("UTF-8");
        int inputLength = inputArray.length;
        // 最大加密字节数，超出最大字节数需要分组加密
        int MAX_ENCRYPT_BLOCK = 117;
        // 标识
        int offSet = 0;
        byte[] resultBytes = {};
        byte[] cache = {};
        while (inputLength - offSet > 0) {
            if (inputLength - offSet > MAX_ENCRYPT_BLOCK) {
                cache = cipher.doFinal(inputArray, offSet, MAX_ENCRYPT_BLOCK);
                offSet += MAX_ENCRYPT_BLOCK;
            } else {
                cache = cipher.doFinal(inputArray, offSet, inputLength - offSet);
                offSet = inputLength;
            }
            resultBytes = Arrays.copyOf(resultBytes, resultBytes.length + cache.length);
            System.arraycopy(cache, 0, resultBytes, resultBytes.length - cache.length, cache.length);
        }
        outStr = java.util.Base64.getEncoder().encodeToString(resultBytes);
        return outStr;
    }

    public static void main(String[] args) {
        System.out.println(URLEncoder.encode("a a"));
    }

    /**
     * 方向控制
     * @param channelId：视频通道编码
     * @param direct：方向：1=上，2=下，3=左，4=右，5=左上，6=左下，7=右上，8=右下
     * @param speed：速度，1 - 8
     * @param command： 0=停止, 1=开启
     * @return
     */
    public static R<IccResponse> ctrlDirect(String channelId, String direct, String speed, String command, String inNet) {
        IccToken token = IccTokenCache.getInstance().getToken();
        if (token == null) {
            return R.failed("token为空");
        }
        StringBuilder builder = new StringBuilder();
        if (StringUtils.isEmpty(inNet) || inNet.equals("0")) {
            builder.append(getRequestUrl("/evo-apigw/admin/API/DMS/Ptz/OperateDirect"));
        } else {
            builder.append(getInRequestUrl("/evo-apigw/admin/API/DMS/Ptz/OperateDirect"));
        }
        JSONObject data = new JSONObject();
        data.put("channelId", channelId);
        data.put("direct", direct);
        data.put("stepX", speed);
        data.put("stepY", speed);
        data.put("command", command);
        data.put("extend", "");
        JSONObject body = new JSONObject();
        body.put("data", data);
        String responseData = IccHttpsURLConnectionUtil.doPost(builder.toString(), JSON.toJSONString(body), token.getHeaderToken());
        try {
            Gson gson = new Gson();
            IccResponse<IccCtrlResult> response = gson.fromJson(responseData, new TypeToken<IccResponse<IccCtrlResult>>(){}.getType());
            return R.ok(response);
        } catch (Exception ex) {
            ex.printStackTrace();
            return R.failed(ex.getMessage());
        }
    }

    /**
     * 变焦等控制
     * @param channelId: 视频通道编码
     * @param operateType： 操作类型：1=变倍，2=变焦，3=光圈
     * @param direct： 方向：1=增加，2=减小
     * @param step： 转动速度
     * @param command： 命令：0=停止动作，1=开启动作
     * @return
     */
    public static R<IccResponse> ctrlCamera(String channelId, String operateType, String direct, String step, String command, String inNet) {
        IccToken token = IccTokenCache.getInstance().getToken();
        if (token == null) {
            return R.failed("token为空");
        }
        StringBuilder builder = new StringBuilder();
        if (StringUtils.isEmpty(inNet) || inNet.equals("0")) {
            builder.append(getRequestUrl("/evo-apigw/admin/API/DMS/Ptz/OperateCamera"));
        } else {
            builder.append(getInRequestUrl("/evo-apigw/admin/API/DMS/Ptz/OperateCamera"));
        }
        JSONObject data = new JSONObject();
        data.put("channelId", channelId);
        data.put("operateType", operateType);
        data.put("direct", direct);
        data.put("step", step);
        data.put("command", command);
        data.put("extend", "");
        JSONObject body = new JSONObject();
        body.put("data", data);
        String responseData = IccHttpsURLConnectionUtil.doPost(builder.toString(), JSON.toJSONString(body), token.getHeaderToken());
        try {
            Gson gson = new Gson();
            IccResponse<IccCtrlResult> response = gson.fromJson(responseData, new TypeToken<IccResponse<IccCtrlResult>>(){}.getType());
            return R.ok(response);
        } catch (Exception ex) {
            ex.printStackTrace();
            return R.failed(ex.getMessage());
        }
    }

    /**
     * 获取巡航路线
     * @param channelId: 通道编码
     * @return 结果
     */
    public static R<IccCruisesResult> getCruisesLine(String channelId) {
        IccToken token = IccTokenCache.getInstance().getToken();
        if (token == null) {
            return R.failed("token为空");
        }
        StringBuilder builder = new StringBuilder();
        builder.append(getRequestUrl("/evo-apigw/admin/API/DMS/Ptz/GetCruises"));
        JSONObject data = new JSONObject();
        data.put("channelId", channelId);
        JSONObject body = new JSONObject();
        body.put("data", data);
        String responseData = IccHttpsURLConnectionUtil.doPost(builder.toString(), JSON.toJSONString(body), token.getHeaderToken());
        try {
            Gson gson = new Gson();
            IccResponse<IccCruisesResult> response = gson.fromJson(responseData, new TypeToken<IccResponse<IccCruisesResult>>(){}.getType());
            return R.ok(response.getData());
        } catch (Exception ex) {
            ex.printStackTrace();
            return R.failed(ex.getMessage());
        }
    }
}
